<!--
 * @Author       : wfl
 * @LastEditors: qiye
 * @description  :
 * @updateInfo   :
 * @Date         : 2023-03-22 12:27:56
 * @LastEditTime: 2023-11-17 10:50:34
-->
<script setup lang="ts" name="TabForm">
import { ElMessage } from 'element-plus'
import { ArrowLeft } from '@element-plus/icons-vue'
import { _, paramType } from 'iking-utils'
import { EApproveCategory, EFlowFormType, ENode } from '@main/views/approve-workflow/enum'
import useTabbarStore from '@g/store/modules/tabbar'
import WorkFlow from '@main/views/approve-workflow/WorkFlow/index.vue'
import { useLoadEditData } from '../load-edit-data'
import DesignBase from './Design/DesignBase.vue'
import AdvanceSetting from './AdvanceSetting/index.vue'
import ValidateModal from './ValidateModal.vue'
import { advanceApi, formApi } from '@/MainApp/apis/approve-center'
import useSettingsStore from '@/global/store/modules/settings'
// const emit = defineEmits(['handLoad'])
// const WorkFlow = defineAsyncComponent(
//   () => import('@main/views/approve-workflow/WorkFlow/index.vue')
// )
export interface IInitiator {
  id?: string
  // 表单编号
  formId: string
  // 表单发起人编号
  initiatorId: string
  // 表单发起人名称
  initiatorName: string
  // 发起人类型,可用值:ALL,USER,ROLE,DEPT,POST
  initiatorType: string
}
export interface IManager {
  id?: string
  // 表单编号
  formId: string
  // 	表单管理者编号
  managerId: string
  // 	表单管理者名称
  managerName: string
  // 管理者类型,可用值:ALL,USER,ROLE,DEPT,POST
  managerType: string
}
export interface IWidget {
  d?: string
  // 表单编号
  formId?: string
  // 表单控件名
  widgetName: string
  // 表单控件标签
  widgetLabel: string
  // 表单控件类型,可用值:TEXT,DATETIME,NUMBER,COLLECTION
  widgetType: string
  // 表单控件字段类型名称
  widgetTypeName?: string
}
export interface IForm {
  id?: string
  // 表单名称
  name?: string
  // 表单图标
  icon?: string
  // 表单所属分组编号
  groupId?: string
  // 表单所属分组名称
  groupName?: string
  // 	表单说明
  remark?: string
  // 	表单状态,可用值:ENABLE,DISABLE
  status?: string
  // 表单是否支持配置发起人
  customizeInitiator?: boolean
  // 表单发起人信息
  initiators?: IInitiator[]
  managers?: IManager[]
}
export interface IFlowForm {
  form?: IForm
  formViewConfig?: {
    id?: string
    property?: string
    widgets?: IWidget[]
    // 表单提交按钮名称
    submitLabel?: string
    // 表单拒绝按钮名称
    refuseLabel?: string
  }
  process?: {
    processNodes?: any[]
  }
  formAdvanceConfigDTO?: any
}
interface TreeNode {
  [key: string]: any
  children?: TreeNode[] | null
}
const router = useRouter()
const route = useRoute()

const currentStep = ref(1)
const JUST_FLOW = route.query?.type === EFlowFormType.已有表单

const step = !JUST_FLOW
  ? [
      {
        id: 1,
        name: '基础设置'
      },
      {
        id: 2,
        name: '表单设计'
      },
      {
        id: 3,
        name: '流程设计'
      },
      {
        id: 4,
        name: '高级设置'
      }
    ]
  : [
      {
        id: 1,
        name: '基础设置'
      },
      {
        id: 3,
        name: '流程设计'
      },
      {
        id: 4,
        name: '高级设置'
      }
    ]

const flowStore = useFlowStore()
const groupNames = ['A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J']

const flowFormData: Ref<any> = ref({
  form: {
    groupId: '',
    remark: '',
    type: '',
    name: '',
    group: '',
    icon: 'ikflow-yonghu',
    iconBackground: '#1e90ff',
    // 描述
    desc: '',
    // 发起人
    initiators: [],
    initiatorsName: '',
    // 管理员
    managers: [],
    managersName: ''

  },
  formViewConfig: {
    property: flowStore.designForm,
    formConfig: {},
    widgets: [],
    ...flowStore.designForm
  },
  process: {
    processNodes: null
  }
})

// 低代码表单空间
const refDesigner: Ref<{
  getFieldWidgets: () => any[]
  getFormJson: () => { formConfig: any; widgetList: any[]; }
  setFormJson: (json: string) => null
  [key: string]: any
} | null | any> = ref(null)

const tabbarStore = useTabbarStore()
const handleBack = (auto = false) => {
  try {
    if (!auto)
      tabbarStore.remove(location.hash.slice(1))
    flowStore.resetForm()
    router.back()
  }
  catch (error) {
  }
}

const { handEditFlow } = useLoadEditData()
onMounted(async () => {
  // 编辑状态时，刷新页面重新获取数据
  const { isEdit, id } = route.query as any
  if (isEdit)
    await handEditFlow({ id })
  flowFormData.value.formViewConfig = {
    property: flowStore.designForm,
    formConfig: {},
    widgets: [],
    ...flowStore.designForm
  }
  refDesigner.value?.setFormJson(flowFormData.value?.formViewConfig?.property)
})

const handActionForm = () => {
  if (JUST_FLOW) {
    const obj = {
      property: {},
      formConfig: flowStore.designForm.formConfig,
      widgets: flowStore.designForm.widgetList
    }
    flowStore.setForm({
      ...obj,
      widgetList: obj.widgets
    })
    return obj
  }
  const formJson = refDesigner.value!.getFormJson()
  flowStore.setForm(formJson)
  const { formConfig, widgetList } = formJson

  return {
    property: JSON.stringify(formJson),
    formConfig,
    widgets: widgetList.map((v: any) => {
      console.log('widgetList v ', v)
      return {
        widgetName: v.id,
        widgetLabel: v.options.label,
        widgetType: v.type?.toLocaleUpperCase()
      }
    })
  }
}
// 切换步骤
const handSelectStep = (item: any) => {
  currentStep.value = item.id
  try {
    if (item.id !== 2) {
      const { property, widgets } = handActionForm()
      flowFormData.value.formViewConfig.property = property
      flowFormData.value.formViewConfig.widgets = widgets
    }
  }
  catch (error) {
    console.warn('error: ', error)
  }
}
// 修改字段名称
const handRename = (node: any) => {
  if (!node?.props?.assignedUser || !paramType.isArray(node?.props?.assignedUser))
    return null
  return node.props.assignedUser.map(
    ({
      elementType: executorType,
      elementName: executorName,
      elementId: executorId
    }: any) => {
      return {
        executorType,
        executorName,
        executorId,
        executorCategory: [EApproveCategory.联系人控件关联成员, EApproveCategory.部门控件关联角色].includes(node?.props?.approvalCategory) ? node.props.approvalCategory : 'APPROVAL'
      }
    }
  )
}
// 如果没有子节点，将clildren置为null
const setEmptyChildren = (node: TreeNode) => {
  if (
    paramType.isObject(node?.children)
    && !Reflect.ownKeys(node?.children).length
  )
    node.children = null
}
// 遍历树
const traverseTree = (node: TreeNode, callback: Function) => {
  callback(node)
  const _tree = node?.children || node?.conditions
  if (!_tree)
    return
  if (node?.children) {
    try {
      const a_tree = paramType.isArray(node?.children)
        ? node?.children
        : [node?.children]
      a_tree.forEach((child: any) => {
        traverseTree(child, callback)
      })
    }
    catch (error) {
      console.info('error: ', error)
    }
  }
  // setEmptyChildren(node)
  if (node?.conditions) {
    const a_tree = paramType.isArray(node?.conditions)
      ? node?.conditions
      : [node?.conditions]
    a_tree.forEach((child: any) => {
      traverseTree(child, callback)
    })
  }
}
const handSetNoBody = (node: any) => {
  return node.props?.reserveApprovals?.map(
    ({
      elementType: executorType,
      elementName: executorName,
      elementId: executorId
    }: any) => {
      return {
        executorType,
        executorName,
        executorId,
        executorCategory: [EApproveCategory.联系人控件关联成员, EApproveCategory.部门控件关联角色].includes(node?.props?.approvalCategory) ? node.props.approvalCategory : 'RESERVE_APPROVAL'
      }
    }
  ) || []
}
// 流程数据组装
const handAssembleProcess = () => {
  const design = _.cloneDeep(flowStore.design.process)

  // 根节点
  const processNodes = {
    ...design,
    name: design.name,
    type: design.type,
    id: design.id,
    approvals: handRename(design),
    // previousId: design.parentId,
    approveType: design.props.approveType,
    approvalCategory: design.props.approvalCategory,
    rejectType: design.props?.refuse?.type
    // children: [],
    // conditions: []
  }

  traverseTree(processNodes.children, (node: any) => {
    if (!node || !Reflect.ownKeys(node).length)
      return
    const data = {
      name: node.name,
      type: node.type,
      // previousId: node?.parentId,
      approveType: node?.props?.approveType,
      approvalCategory: node?.props?.approvalCategory,
      // 多人审批方式,可用值:NONE,SEQUENCE,ALL,ANY
      multiExecutorType: node.props?.mode,
      // 是否由发起人指定抄送人
      initiatorSpecifyCarbonCopy: node.props?.shouldAdd,
      // 发起人自选-选择范围类型,可用值:ALL,BY_ROLE,BY_USER
      initiatorSpecifiedScopeType: node.props?.initiatorSpecifiedScopeType,
      approvals: handRename(node),
      // 部门控件
      deptWidgetName: node?.props?.formDep,
      // 组织控件
      organizationWidgetName: node?.props?.formOrg,
      // 联系人控件
      usertWidgetName: node?.props?.formUser,
      // ================= 非直系节点===================
      // 审批人为空时  审批对象信息
      reserveApprovals: handSetNoBody(node),
      // 发起人自选-选人方式是否单选
      singleApproval: !(node?.props?.selfSelect?.multiple && node.props?.approvalCategory === EApproveCategory.发起人自选),
      // 审批人为空时的策略,可用值:AUTO_PASS,TRANSMIT_TO_MANAGER,SPECIFIED_USER
      // emptyApprovalStrategy
      executorEmptyStrategy: node.props?.nobody?.handler,
      // 审批人拒绝后的操作类型,可用值:END,TO_SPECIFIED
      rejectType: node.props?.refuse?.type,
      // 审批人拒绝后退回至指定节点的节点标识
      rejectToNodeCode: node.props?.refuse?.target,
      // 退回时是否直接退回到发起节点
      backToInitiator: node.props?.backToInitiator
    }
    if (!node?.children)
      return
    setEmptyChildren(node)
    const NODE_TYPE = node?.type || node?.children?.type
    switch (NODE_TYPE) {
      case ENode.APPROVAL:
      case ENode.DISPOSE:
        Object.assign(node, data)
        break
      case ENode.CC:
        Object.assign(node, data)
        break
      default:
        Object.assign(node, data)
        // 分支或条件节点
        // 设置分支节点别名
        if (node.branchs) {
          if (node.children?.type === ENode.EMPTY) {
            try {
              node.children = node.children.children
              node.children.parentId = node.id
              if (!node?.children?.type)
                node.children = null
            }
            catch (error) {
              console.info('error: ', error)
            }
          }
          node.conditions = node?.branchs?.map((item: any) => {
            const conditionGroups = item?.props?.groups?.map((group: any, index: any) => {
              const comparisons = group.conditions.map((cond: any) => {
                return {
                  id: cond.id,
                  nodeId: cond.id,
                  widgetName: cond.id,
                  widgetDescription: cond.title,
                  comparator: cond.compare,
                  compareToValues: cond.value,
                  datePattern: cond.valueType
                }
              })
              return {
                name: `条件组${groupNames[index]}`,
                comparisons
              }
            })

            return {
              id: item.id,
              type: node.type,
              name: item.name,
              children: item.children,
              conditionOrder: item.conditionOrder || null,
              conditionGroups: item.name === '系统默认条件' ? null : conditionGroups
            }
          })
          delete node.branchs
          node.type = ENode.BRANCH
        }
        break
    }
    if (!node?.children?.type)
      node.children = null
  })

  return processNodes
}

const loading = ref(false)
// 流程校验框
const showValidate = ref(false)
// 流程实例
const flowRef = ref<{ flowRef: { validate: Function; }; }>()
// 表单实例
const formRef = ref<{ ruleBaseRef: { validate: Function; }; }>()
const errorMap = ref(new Map())

// 确认发布
const sureToPublish = async (back = true) => {
  loading.value = true
  try {
    const { assignedUser } = flowStore.design.process.props
    const { managers } = flowStore.design.base
    const { property, widgets, formConfig = {} } = handActionForm()
    const type = unref(route?.query).type || EFlowFormType.流程表单
    // 是否为流程表单
    const isProcess = type === EFlowFormType.流程表单
    const param = {
      // 表单信息
      ...flowStore.design.base,
      // 表单是否支持配置发起人
      customizeInitiator: isProcess,
      type,
      // 已有表单时 传入businessType为表单businessType（flowStore?.designForm?.formConfig?.formData?.businessType）
      businessType: isProcess ? 'APPROVE_CENTER' : (flowStore?.designForm?.formConfig?.formData?.businessType || null),
      initiators: assignedUser?.length
        ? assignedUser.map(
          ({
            elementName: initiatorName,
            elementId: initiatorId,
            elementType: initiatorType
          }: any) => {
            return {
              initiatorName,
              initiatorId,
              initiatorType
            }
          }
        )
        : [
            {
              initiatorType: 'ALL'
            }
          ],
      managers: managers?.length
        ? managers.map(
          ({
            elementName: managerName,
            elementId: managerId,
            elementType: managerType
          }: any) => {
            return {
              managerName,
              managerId,
              managerType
            }
          }
        )
        : [
            {
              managerType: 'ALL'
            }
          ],
      // 自定义表单
      formViewConfig: {
        property: typeof property === 'string' ? property : JSON.stringify(property),
        widgets,
        ...formConfig,
        submitLabel: '',
        refuseLabel: ''
      },
      // 流程
      process: {
        rootNode: handAssembleProcess(),
        property: JSON.stringify(flowStore.design)
      },
      // 高级配置
      formAdvanceConfig: {
        reportTemplateId: flowStore.design.advance?.reportTemplateId
      }
    }
    if (type === EFlowFormType.已有表单 && !param.id)
      param.id = flowStore?.designForm?.formConfig?.formData?.id

    console.info('提交数据： ', param)
    const isEdit = route.query.isEdit
    const ret = isEdit
      ? await formApi.editForm(param)
      : await formApi.addForm(param)
    const { success, msg } = ret
    if (success) {
      loading.value = false
      ElMessage.success(msg)
      showValidate.value = false
      // formRef.value?.ruleBaseRef?.validate()
      if (back)
        handleBack()
    }
    else {
      loading.value = false
      ElMessage.error(msg)
    }

    return ret
  }
  catch (error) {
    ElMessage.error('提交失败')
    console.info(error)
    loading.value = false
  }
}
// 发布
const handPublish = async () => {
  showValidate.value = true
}

watch(
  () => flowFormData.value.formViewConfig.property,
  (v: any) => {
    flowFormData.value.formViewConfig.property = v
    flowFormData.value.formViewConfig.widgets = v.widgetList
    if (typeof v === 'string')
      flowStore.setForm(JSON.parse(v))
  },
  { deep: true }
)
const base = computed(() => {
  return flowStore.design.base
})
const isFull = ref(false)
const handFullScreen = () => {
  useMainPage().maximize(!isFull.value)
  isFull.value = !isFull.value
}
const settingsStore = useSettingsStore()
watch(() => settingsStore.mainPageMaximizeStatus, val => {
  if (!val)
    isFull.value = false
})
// 高级配置
const advanceSettingRef = ref<any>(null)
// TODO 流程预览
const handPreview = () => {
}
/** 高级设置——打印 start */
const isPrintTemplateEdit = computed(() => flowStore.design.advance?.isPrintTemplateEdit)
const handleSave = async () => {
  // // 保存
  const param: { formId: string; reportTemplateId: string; } = {
    formId: flowStore.design.base.id,
    reportTemplateId: advanceSettingRef.value?.getPrintId()
  }

  const { success, msg } = await advanceApi.bindReportTemplate(param)
  if (success) {
    ElMessage.success(msg)
    // 返回列表
    handleBack()
  }
  else {
    ElMessage.error(msg)
  }
}
/** 高级设置——打印 end */

// 给后代提供
provide('sureToPublish', sureToPublish)
</script>

<template>
  <div class="ikflow-tab-aform">
    <IkPageHeader
      :icon="`ikflow ${base?.icon || flowFormData.form?.icon}`"
      :background-color="base?.iconBackground || flowFormData.form?.iconBackground"
      @back="handleBack(true)"
    >
      <template #left>
        <div class="flex items-center">
          <el-icon>
            <ArrowLeft />
          </el-icon>
          <IkIconImage />
        </div>
      </template>
      <template #center>
        <ul>
          <li
            v-for="(item, index) in step"
            :key="index"
            :class="{ active: currentStep === item.id }"
            @click="handSelectStep(item)"
          >
            <span>{{ item.id }}</span>
            {{ item.name }}
          </li>
        </ul>
      </template>
      <template #right>
        <div class="m-w-[222px]">
          <el-button @click="handFullScreen">{{ isFull ? '退出全屏' : '全屏' }}</el-button>
          <el-button @click="handPreview">预览</el-button>
          <el-button v-if="!isPrintTemplateEdit" type="primary" @click="handPublish">发布</el-button>
          <el-button v-else type="primary" @click="handleSave">保存</el-button>
        </div>
      </template>
    </IkPageHeader>
    <div v-loading="loading" class="flex justify-center form-content">
      <DesignBase v-show="currentStep === 1" ref="formRef" />
      <VFormDesigner
        v-if="$route.query.type !== EFlowFormType.已有表单"
        v-show="currentStep === 2"
        ref="refDesigner"
        :form-json="flowFormData.formViewConfig.property"
      />
      <WorkFlow
        v-show="currentStep === 3"
        ref="flowRef"
        :data="flowFormData"
        :process="flowFormData.process.processNodes"
      />
      <AdvanceSetting v-if="currentStep === 4" ref="advanceSettingRef" />
      <ValidateModal
        :show-validate="showValidate"
        :error-map="errorMap"
        :flow-valid="flowRef?.flowRef"
        :form-valid="formRef?.ruleBaseRef"
        :design-valid="refDesigner"
        :loading-publish="loading"
        @close="showValidate = false"
        @publish="sureToPublish"
      />
    </div>
  </div>
</template>

<style lang="scss" scoped>
.ikflow-tab-aform {
  flex: 1;
  // margin-top: calc(var(--ik-margin-top-with-bread) - 2px);

  .el-affix {
    position: fixed;
    z-index: 9;
    width: calc(100% - var(--ik-sub-sidebar-actual-width)) !important;
    transition: width .25s ease;

    :deep(.el-affix--fixed){
      top: unset !important;
    }
  }

  .center {
    ul {
      display: flex;

      li {
        color: var(--el-text-color-regular);
        margin-right: 32px;
        font-size: 14px;
        cursor: pointer;
        display: flex;
        align-items: center;

        &.active {
          color: var(--el-color-primary);

          span {
            color: #fff;
            border-color: var(--el-color-primary);
            background: var(--el-color-primary);
          }
        }

        &:hover {
          color: var(--el-color-primary);

          span {
            color: #fff;
            border-color: var(--el-color-primary);
            background: var(--el-color-primary);
          }
        }

        span {
          margin-right: 5px;
          transition: all 0.25s ease-in-out;
          font-size: 14px;
          display: inline-flex;
          align-items: center;
          justify-content: center;
          width: 18px;
          height: 18px;
          border: 1px solid;
          border-radius: 50%;
        }
      }
    }
  }

  .form-content {
    min-height: calc(100% - var(--bar-height) - 32px);
    position: relative;
    user-select: none;
    width: 100%;
    overflow: auto;
    top: 82px;
  }
}
</style>

<style lang="scss">
.main-page-maximize {
  .ikflow-tab-aform {
    width: 100%;

    .el-affix {
      top: 0;
      width: 100% !important;

      .el-affix--fixed {
        top: 0 !important;
      }
    }
  }
}

.ikflow-tab-aform {
  .node {
    box-sizing: content-box;
  }
}
</style>
